import $ from 'jquery';
import Clipboard from 'clipboard';
import CodeMirror from 'codemirror';
import 'codemirror/lib/codemirror.css';
import 'codemirror/theme/mdn-like.css';
import 'codemirror/theme/solarized.css';
import 'codemirror/theme/yeti.css';
import 'codemirror/mode/xml/xml.js';
import 'codemirror/mode/javascript/javascript.js';
import 'codemirror/mode/css/css.js';
import 'codemirror/mode/htmlmixed/htmlmixed.js';
import 'codemirror/addon/edit/matchbrackets.js';
import 'common/css/com.less';
import './index.less';
import 'layout/header/index.js';
import SideBar from 'layout/sidebar/index.js';

const mockCode = `<script type='text/javascript'>
                    var mock = {
                        log: function(result) {
                            window.parent.setIFrameResult('log', result);
                        },
                        error: function(result) {
                            window.parent.setIFrameResult('error', result);
                        }
                    }
                    console = mock;
                    window.Konsole = {
                        exec: function(code) {
                            code = code || '';
                            try {
                                var result = window.eval(code);
                                window.parent.setIFrameResult('result', result);
                            } catch (e) {
                                window.parent.setIFrameResult('error', e);
                            }
                        }
                    }
                </script>`;

const example = {
  sCopyTarget: '#codes',
  editor: null,
  scrolled: false,
  timer: null,
  url: 'mapv/heatmap',
  iframeWrapper: $('#iframe_wrapper'),
  iframe: $('#js_iframe'),
  clipboard: null,
  codeWrapWidth: null,
  init: function() {
    const hash = window.location.hash;
    if (hash) {
      this.url = hash.substring(1);
    }
    this.count = 0;
    this.console();
    const sideBar = new SideBar();
    sideBar.init();
    const self = this;
    this.getCode(function(res) {
      $(self.sCopyTarget).val(res);
      self.bind();
    });
  },
  getCode: function(callback) {
    $.ajax({
      type: 'get',
      url: `./js_thematic_map_example/${this.url}.html`,
      dataType: 'text',
      success: function(response) {
        callback && callback(response);
      }
    });
  },
  changeExample: function() {
    const self = this;
    const hash = window.location.hash;
    if (hash) {
      this.url = hash.substring(1);
    }
    this.getCode(function(res) {
      $(self.sCopyTarget).val(res);
      localStorage.code = res;
      self.editor.setValue(res);
      self.fRun();
      $('#code_run').trigger('refresh');
    });
  },
  bind: function() {
    const self = this;
    const sCopyTarget = self.sCopyTarget;
    localStorage.code = $(sCopyTarget).val();
    self.editor = null;
    function initEditor() {
      if (!self.editor) {
        self.editor = CodeMirror.fromTextArea(
          document.getElementById('codes'),
          {
            // theme: 'mdn-like',
            // theme: 'solarized light',
            // theme: 'yeti',
            lineWrapping: true, // 是否显示scroll
            lineNumbers: true, // 是否显示number
            styleActiveLine: true,
            matchBrackets: true,
            mode: 'htmlmixed',
            viewportMargin: Infinity
          }
        );
      } else {
        self.editor.setValue($(sCopyTarget).val());
      }
    }

    initEditor();

    self.timer = setInterval(function() {
      const iFrame = document.getElementById('js_iframe');
      if (!iFrame) {
        return;
      }
      const content = iFrame.contentWindow || iFrame.contentDocument;
      const doc = content.document ? content.document : content;
      if (!doc) {
        clearInterval(self.timer);
        self.timer = null;
      }
      if (doc.readyState === 'complete') {
        clearInterval(self.timer);
        self.timer = null;
        self.fRun();
      }
    }, 100);
    const oCode = $('#code_wrapper');
    const bFoldedStorage = self.getStorage();
    const iCodeMoveLength = parseInt(self.getStorage('codeMoveLength'));
    let iCodeWidth = iCodeMoveLength || oCode.width();
    const oArrow = $('#code_arrow');
    const oCodeCore = $('#code_core');
    const oIframeWrapper = $('div.js_demo_body');
    let iIframeMargin = parseInt(oIframeWrapper.css('margin-right'));
    let bFolded = false;

    if (bFoldedStorage === 'true') {
      bFolded = true;
    } else if (bFoldedStorage === 'false') {
      bFolded = false;
    }
    if (bFolded) {
      oCodeCore.css({ width: 0 });
      oArrow.addClass('show');
      oArrow.removeClass('go_back');
    }
    oCode.addClass('visible');
    oArrow.addClass('show');
    if (!bFolded) {
      oCodeCore.css('width', iCodeWidth);
      oIframeWrapper.css('margin-right', iIframeMargin + iCodeWidth);
      oArrow.addClass('go_back');
    }
    oArrow.click(function() {
      // destory
      if (self.codeWrapWidth) {
        iIframeMargin = iCodeWidth = self.codeWrapWidth;
      } else if (iCodeMoveLength) {
        // 之前拖动的距离
        iIframeMargin = iCodeWidth = iCodeMoveLength;
      }

      if (oArrow.hasClass('go_back')) {
        oCodeCore.animate({ width: 0 }, function() {
          oIframeWrapper.css({ marginRight: 0 });
        });

        oArrow.removeClass('go_back');
        self.setStorage(true);
      } else {
        oCodeCore.animate({ width: iCodeWidth }, function() {
          oIframeWrapper.css({ marginRight: iCodeWidth });
        });

        oArrow.addClass('go_back');
        self.setStorage(false);
      }
    });

    $('#code_restore').click(function() {
      self.editor.setValue(localStorage.code);
      self.fRun();
      $('#code_run').trigger('refresh');
    });

    $('#code_run').click(function() {
      self.fRun();
      $(this).trigger('refresh');
    });
  },
  createIframe: function() {
    this.iframe = document.createElement('iframe');
    this.iframeWrapper.append(this.iframe);
  },
  destroyIframe: function() {
    if (this.iframe === null) {
      return;
    }
    // 把iframe指向空白页面，释放内存
    this.iframe.src = 'about:blank';
    try {
      this.iframe.contentWindow.document.write('');
      this.iframe.contentWindow.document.clear();
    } catch (e) {};
    // 把iframe从页面移除
    this.iframeWrapper.empty();
    this.iframe = null;
  },
  fRun: function() {
    const self = this;
    let iframeContent = $(self.sCopyTarget).val();
    if (self.editor) {
      iframeContent = self.editor.getValue();
    }
    const nr = iframeContent.indexOf('<body>');
    const iframeHead = iframeContent.slice(0, nr);
    const iframeFooter = iframeContent.slice(nr, iframeContent.length);
    self.createIframe();
    if (!self.iframe) {
      return;
    }

    let doc = self.iframe.contentWindow || self.iframe.contentDocument;
    if (doc.document) {
      doc = doc.document;
    }
    if (!doc) {
      return;
    }
    doc.open();
    doc.write(iframeHead);
    doc.write(mockCode);
    doc.write(iframeFooter);
    doc.close();
  },
  setStorage: function(value, keyName = 'folded') {
    if (!window.localStorage) return false;

    localStorage.setItem(keyName, value);
  },
  getStorage: function(keyName = 'folded') {
    if (!window.localStorage) return null;

    return localStorage.getItem(keyName);
  },
  copy: function() {
    const self = this;

    /** 复制功能 **/
    function sCopy() {
      let iframeContent = $(self.sCopyTarget).val();
      if (self.editor) {
        iframeContent = self.editor.getValue();
      }
      return iframeContent;
    }

    // 复制功能绑定
    self.clipboard = new Clipboard('#code_copy', {
      text: function() {
        return sCopy();
      }
    });
    self.clipboard
      .on('success', function(e) {
        e.clearSelection();
      })
      .on('error', function(e) {
        console.error('Action:', e.action);
        console.error('Trigger:', e.trigger);
      });
  },
  console: function() {
    const self = this;
    const editor = CodeMirror(document.getElementById('code_console'), {
      value: "console.log('可以在这里进行实时调试，输入代码后按Enter执行')",
      mode: 'javascript'
      // autofocus: true,
    });
    let sandbox = document.getElementById('js_iframe');
    editor.setOption('extraKeys', {
      Enter: function() {
        var code = editor.getValue();
        if (code.length > 0) {
          window.setIFrameResult('code', code);
          sandbox.contentWindow.Konsole.exec(code);
        }
      }
    });

    $('#code_run').on('refresh', function() {
      // destory
      sandbox = document.getElementById('js_iframe');
    });

    $('#code_clear').on('click', function(e) {
      // destory
      e.preventDefault();
      $('#output').empty();
      updateContentMinHeight();
    });

    var jsDemoBody = $('div.js_demo_body');
    var oCodeCore = $('#code_core');
    var jsConsole = $('#js_console');
    var output = $('#output');
    var jsContent = jsConsole.find('.content');
    var consoleWrapper = $('#console_wrapper');
    var body = oCodeCore.find('.code_body');

    function updateContentMinHeight() {
      var minHeight = Math.max(jsConsole.height() - output.height(), 30);
      jsContent.css('min-height', minHeight);
      jsContent
        .find('.CodeMirror')
        .css('height', minHeight > 30 ? minHeight : 'inherit');
    }

    updateContentMinHeight();

    function line(type, text) {
      var div = document.createElement('div');
      div.appendChild(document.createTextNode(text));
      $(div).addClass('output-' + type);
      return div;
    }

    window.setIFrameResult = function(type, text) {
      $('#output').append(line(type, text));
      updateContentMinHeight();
      jsConsole.scrollTop(jsConsole.height());
      editor.setValue('');
    };
    var dragObj = {};
    $('body')
      .on('mousedown', '#console_wrapper .code_head', function(e) {
        e.preventDefault();
        dragObj.down = true;
        dragObj.top = consoleWrapper[0].offsetTop;
        dragObj.y = e.clientY;
      })
      .on('mousemove', function(e) {
        if (!dragObj.down) {
          return;
        }
        var y = e.clientY;
        var top = dragObj.top - (dragObj.y - y);
        var total = $('#code_related').height();
        var consolePercent =
          Math.round(((total - top) * 1000000) / total) / 10000;
        if (consolePercent > 80 || consolePercent < 20) {
          return;
        }
        consoleWrapper.css('height', consolePercent + '%');
        body.css('bottom', consolePercent + '%');
        updateContentMinHeight();
      })
      .on('mouseup', function() {
        delete dragObj.down;
      });

    var dragColObj = {};
    var mapMask = $('#map_mask');
    $('body')
      .on('mousedown', '#col_resize', function(e) {
        e.preventDefault();
        dragColObj.down = true;
        dragColObj.x = e.clientX;
        dragColObj.width = $(window).width();
        mapMask.addClass('show');
      })
      .on('mousemove', function(e) {
        const oThis = $(this);
        const bodyWidth = oThis.width();

        if (!dragColObj.down) {
          return;
        }
        var x = e.clientX;
        var result = dragColObj.width - x;

        if (result > bodyWidth * 0.7 || result < 300) {
          return;
        }

        self.codeWrapWidth = result;
        oCodeCore.width(result);
      })
      .on('mouseup', function() {
        var iCodeMoveLength = oCodeCore.width();
        jsDemoBody.css({ marginRight: iCodeMoveLength });
        !!iCodeMoveLength && self.setStorage(iCodeMoveLength, 'codeMoveLength');
        mapMask.removeClass('show');
        self.editor.refresh();
        delete dragColObj.down;
      });
  },
  destroy() {
    let self = this;
    if (this.timer) {
      clearInterval(this.timer);
      this.timer = null;
    }
    if (self.clipboard) {
      self.clipboard.off('success');
      self.clipboard.off('error');
    }
    self.destroyIframe();
    self.count = 0;
  }
};

$(function() {
  example.init();
  if ('onhashchange' in window) {
    window.onhashchange = function(ev) {
      example.destroy();
      example.changeExample();
    };
  }
});
